﻿using System;
using System.Collections.Generic;
using System.Text;
using ChaosEngine.EngineCore;
using ChaosEngine.EngineCore.Graph;
using ChaosEngine.EngineCore.Graph.Logics;

namespace ChaosEngine.EngineCore
{
    public abstract class NodeGraph : vObj 
    {

        public static class Current
        {

            public static Dictionary<string, NodeGraph> Map = new Dictionary<string, NodeGraph>();

            public static NodeGraph GetGraph(string name)
            {

                return Map[name];

            }
            public static NodeGraph GetCurrent(){
                return Map["_Current"];
            }
            public static void SetCurrent(NodeGraph graph)
            {

                if(Map.ContainsKey("_Current")){
                    Map.Remove("_Current");
                }

                Map.Add("_Current",graph);

            }

        }
        public string Name { get; set; }

        public GraphNode Root { get; set; }
    
        public NodeGraph(string name)
        {

            Name = name;

            Current.Map.Add(name,this);

            Root = CreateRoot();


        }

        public abstract GraphNode CreateRoot();

    }
    
    
    public class GraphNode
    {

        public string Name { get; set; }

        public Dictionary<string, GraphNode> Nodes = new Dictionary<string, GraphNode>();

        public GraphNode Parent { get; set; }

        public Dictionary<string,dynamic> LogicMap = new Dictionary<string,dynamic>();

        public GraphNode(string name,GraphNode parent)
        {

            Name = name;
            
            if(parent!=null){
                parent.AddNode(this);
            }

        }



        public void AddLogic(dynamic logic){

            LogicMap.Add(logic._TYPE, logic);
            logic.Owner = this;

        }

        public NodeLogic GetLogic(string type)
        {

            return LogicMap[type];

        }

        public bool HasLogic(string type){

            return LogicMap.ContainsKey(type);

        }

       

        public virtual void OnCreate()
        {
            foreach(var l in LogicMap.Values){
                l.OnCreate();
            }     
            foreach(var n in Nodes.Values)
            {
                n.OnCreate();            
            }
        }

        public virtual void OnLogic()
        {
            foreach (var l in LogicMap.Values)
            {
                l.OnLogic();
            }
            foreach (var n in Nodes.Values)
            {
                n.OnLogic();
            }
        }

        public virtual void OnPostPhysics()
        {
            foreach (var l in LogicMap.Values)
            {
                l.OnPostPhysics();
            }
            foreach (var n in Nodes.Values)
            {
                n.OnPostPhysics();
            }
        }

        public virtual void OnPreDraw()
        {
            foreach (var l in LogicMap.Values)
            {
                l.OnPreDraw();
            }
            foreach (var n in Nodes.Values)
            {
                n.OnPreDraw();
            }

        }

        public virtual void OnDraw(){

            foreach (var l in LogicMap.Values)
            {
                l.OnDraw();
            }
            foreach (var n in Nodes.Values)
            {
                n.OnDraw();
            }

        }

        public virtual void OnPostDraw()
        {
            foreach (var l in LogicMap.Values)
            {
                l.OnPostDraw();
            }
            foreach (var n in Nodes.Values)
            {
                n.OnPostDraw();
            }
        }

        public virtual bool ShouldQuit()
        {
            foreach (var l in LogicMap.Values)
            {
                if (l.ShouldQuit()) return true;
            }
            foreach (var n in Nodes.Values)
            {
                if (n.ShouldQuit()) return true;
            }
            return false;
        }
        
        public List<GraphNode> GetNodesWithLogic(string type,List<GraphNode> nodes){
            
            if(nodes==null){
                nodes = new List<GraphNode>();
            }

            if(LogicMap.ContainsKey(type)){
                nodes.Add(this);
            }

            foreach(var n in Nodes.Values)
            {
                n.GetNodesWithLogic(type, nodes);
            }

            return nodes;

        }

        public GraphNode AddNode(GraphNode node){
            
            Nodes.Add(node.Name, node);
            node.Parent = this;
            
            return node;

        }

    }

    public class NodeLogic
    {
        public string _TYPE { get; private set; }
        public GraphNode Owner { get; set; }
   
        public NodeLogic(string _type){
            _TYPE = _type;
        }

       public virtual void OnCreate(){

       }

        public virtual void OnLogic(){

        }

        public virtual void OnPostPhysics(){

        }

        public virtual void OnPreDraw(){

        }

        public virtual void OnDraw(){

        }

        public virtual void OnPostDraw(){

        }

        public virtual bool ShouldQuit(){
            return false;
        }


    }

}
